/**
 * 
 */
package com.jolestar.yayaweibotong.dao;

import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.repackaged.com.google.common.base.Predicate;
import com.google.appengine.repackaged.com.google.common.collect.Iterables;
import com.google.appengine.repackaged.com.google.common.collect.Lists;
import com.jolestar.yayaweibotong.ServiceType;

/**
 * @author jolestar@gmail.com
 * 
 */
public class UserDomain extends AbstractDomain {

	public static enum SyncType {
		MasterSlave(0), EachOther(1);
		private int value;

		SyncType(int value) {
			this.value = value;
		}

		public int getValue() {
			return this.value;
		}

		public static SyncType fromInt(int value) {
			for (SyncType type : SyncType.values()) {
				if (value == type.value) {
					return type;
				}
			}
			return SyncType.MasterSlave;
		}

	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 6968241359902993658L;
	public static final String PASSWORD_PROPERTY = "password";
	public static final String CREATED_AT_PROPERTY = "created_at";
	public static final String SYNCED_PROPERTY = "synced";
	public static final String SYNC_TYPE_PROPERTY = "sync_type";
	public static final String ACTIVITY_PROPERTY = "activity";

	private List<AccountDomain> accounts;
	private AccountDomain masterAccount;

	/**
	 * @param password
	 * @param serviceType
	 * @param id
	 */
	public UserDomain(String email, String password) {
		super(ServiceType.yaya, email);
		this.setPassword(password);
		this.set(SYNCED_PROPERTY, true);
		this.set(ACTIVITY_PROPERTY, false);
	}

	public UserDomain(Entity entity) {
		super(entity);
	}

	public String getName() {
		return this.getEmail();
	}

	public String getEmail() {
		return this.getOriginalId();
	}

	public String getSafeEmail() {
		return this.getEmail().replace("@", "-at-").replace(".", "-dot-");
	}

	public String getPassword() {
		return this.get(PASSWORD_PROPERTY);
	}

	public void setPassword(String password) {
		this.set(PASSWORD_PROPERTY, password);
	}

	public AccountDomain getMasterAccount() {
		if (this.masterAccount == null) {
			this.reloadAccount();
		}
		return this.masterAccount;
	}

	public List<AccountDomain> getSlaveAccounts() {
		if (this.accounts == null) {
			this.reloadAccount();
		}
		if (this.accounts.isEmpty()) {
			return Collections.emptyList();
		}
		return Lists.newUnmodifiableArrayList(Iterables.filter(this.accounts,
				slaveAccountFilter));
	}

	public List<AccountDomain> getAllAccounts() {
		if (this.accounts == null) {
			this.reloadAccount();
		}
		return accounts;
	}

	public boolean isActivity() {
		return this.get(ACTIVITY_PROPERTY);
	}

	public void reloadAccount() {
		Query query = new Query(AccountDomain.class.getName());
		query.addFilter(AccountDomain.USER_PROPERTY,
				Query.FilterOperator.EQUAL, this.getKey());
		List<AccountDomain> accounts = Lists.newUnmodifiableArrayList(Iterables
				.filter(DomainFactory.<AccountDomain> getListByQuery(query),
						new Predicate<AccountDomain>() {

							@Override
							public boolean apply(AccountDomain account) {
								if (!account.getServiceType().isEnable()) {
									if (account.isMaster()) {
										account.setMaster(false);
										account.save();
									}
									return false;
								}
								if (account.isMaster()) {
									UserDomain.this.masterAccount = account;
								}
								return true;
							}
						}));
		this.accounts = accounts;
		this.checkActivity();
	}

	private void checkActivity() {
		int activityAccount = 0;
		for(AccountDomain account:this.accounts){
			if(account.isActivity()){
				activityAccount++;
			}
		}
		switch (this.getSyncType()) {
		case MasterSlave:
			if (this.masterAccount != null && this.masterAccount.isActivity()
					&& activityAccount >= 2) {
				this.set(ACTIVITY_PROPERTY, true);
				this.save();
			} else {
				this.set(ACTIVITY_PROPERTY, false);
				this.save();
			}
			break;
		case EachOther:
			if (activityAccount >= 2) {
				this.set(ACTIVITY_PROPERTY, true);
				this.save();
			} else {
				this.set(ACTIVITY_PROPERTY, false);
				this.save();
			}
			break;
		}
	}

	public void setMasterAccount(String masterKey) {
		if (this.accounts == null) {
			this.reloadAccount();
		}
		if (this.masterAccount != null
				&& this.masterAccount.getKeyName().equals(masterKey)) {
			return;
		}
		for (AccountDomain account : this.accounts) {
			if (account.getKeyName().equals(masterKey)) {
				account.setMaster(true);
				account.save();
				if (this.masterAccount != null) {
					this.masterAccount.setMaster(false);
					this.masterAccount.save();
				}
				this.masterAccount = account;
				break;
			}
		}
		this.checkActivity();
	}

	public void setActivityAccounts(String[] accountKeys) {
		if (this.accounts == null) {
			this.reloadAccount();
		}
		for (AccountDomain account : this.accounts) {
			account.setActivity(ArrayUtils.contains(accountKeys,
					account.getKeyName()));
			account.save();
		}
		this.checkActivity();
	}

	/**
	 * 该用户的微博是否被完全同步
	 * 
	 * @return
	 */
	public boolean isSynced() {
		return this.get(SYNCED_PROPERTY, true);
	}

	public void setSynced(boolean synced) {
		this.set(SYNCED_PROPERTY, synced);
	}

	public SyncType getSyncType() {
		Long value = this.get(SYNC_TYPE_PROPERTY, new Long(0));
		return SyncType.fromInt(value.intValue());
	}

	public void setSyncType(SyncType syncType) {
		this.set(SYNC_TYPE_PROPERTY, new Long(syncType.value));
	}

	private static Predicate<AccountDomain> slaveAccountFilter = new Predicate<AccountDomain>() {

		@Override
		public boolean apply(AccountDomain account) {
			if (account.isMaster()) {
				return false;
			}
			return true;
		}

	};

}
